﻿using System;
using System.Collections.Generic;
using Baseballdata.Context;
using Baseballdata.Data;
using MPI;
using System.Data.Linq;
using System.Linq;
using System.Text;
namespace BattersHPC
{
    class Program
    {
        private double getStd(List<double> dbList)
        {
            double avg = dbList.Average();
            double sumOfDev = 0;
            foreach (double value in dbList)
            {
                sumOfDev += (value) * (value);
            }
            double soda = sumOfDev / dbList.Count;
            return Math.Sqrt(soda - (avg * avg));
        }
        private double getMean(List<double> dbLst)
        {
            double mean = 0;
            foreach (double average in dbLst)
            {
                mean += average;
            }
            mean /= dbLst.Count;
            return mean;
        }

        private double getZScore(double stats, double mean, double std)
        {

            double zScore = 0;
            zScore = ((stats - mean) / std);

            return zScore;
        }
        static void Main(string[] args)
        {
            using (new MPI.Environment(ref args))
            {
                Intracommunicator comm = Communicator.world;
                if (comm.Rank == 0)
                {
                    Program newPrg = new Program();
                    List<double> hofDbls = new List<double>();
                    List<double> hofTrips = new List<double>();
                    List<double> hofHits = new List<double>();
                    List<double> hofABS = new List<double>();
                    List<double> hofHRS = new List<double>();
                    List<double> hofRuns = new List<double>();
                    List<double> hofRBIS = new List<double>();
                    List<double> hofSBS = new List<double>();
                    List<double> hofAVG = new List<double>();
                    List<double> nwDls = new List<double>();
                    double zValueDoubles = 0;
                    double zValueTrips = 0;
                    double zValueHits = 0;
                    double zValueABS = 0;
                    double zValueHRS = 0;
                    double zValueRuns = 0;
                    double zValueRBIS = 0;
                    double zValueSBS = 0;
                    double zValueAVG = 0;
                    string hofPlayerid = null;
                    Dictionary<string, double> zscore = new Dictionary<string, double>();
                    /*Console.WriteLine("Enter Id: ");
                    hofPlayerid = Console.ReadLine();*/
                    BaseballdataDataContext db = new BaseballdataDataContext();
                    var results = from hof in db.HallOfFames
                                  where hof.hofID == hofPlayerid
                                  select hof;
                    Console.WriteLine("start printing-------------");
                    foreach (var q in results)
                    {
                        Console.WriteLine("{0},{1}", q.hofID.Trim(), q.inducted);
                    }
                    Console.WriteLine("end printing--------");
                    //Start
                    DateTime startTime = DateTime.Now;
                    var rslt = from hof in db.HallOfFames
                               where hof.inducted.Equals('Y') && hof.category == "Player"
                               //&& hof.hofID == hofPlayerid
                               select hof;

                    Console.WriteLine("start for only Y---------");
                    var count = 0;
                    foreach (var q in rslt)
                    {
                        var fld = (from f in db.Fieldings
                                   join m in db.Masters on f.playerID equals m.playerID
                                   where (!f.POS.Equals('P') && q.hofID == m.hofID)
                                   orderby f.playerID ascending
                                   group f by f.playerID into field
                                   where field.Count() > 10
                                   select new
                                   {
                                       Id = field.Key
                                   }).Distinct();
                        foreach (var n in fld)
                        {
                            var master = from b in db.Battings
                                         join m in db.Masters on b.playerID equals m.playerID
                                         where (n.Id == b.playerID)
                                         group b by b.playerID into batting
                                         //&& hof.hofID == hofPlayerid
                                         select new
                                         {
                                             Id = batting.Key,
                                             Doubles = batting.Average(i => i._2B),
                                             Triples = batting.Average(i2 => i2._3B),
                                             Hits = batting.Average(i3 => i3.H),
                                             AB = batting.Average(i8 => i8.AB),
                                             HomeRuns = batting.Average(i4 => i4.HR),
                                             Runs = batting.Average(i5 => i5.R),
                                             RBI = batting.Average(i6 => i6.RBI),
                                             StolenBases = batting.Average(i7 => i7.SB),
                                             Avg = (Double)(((Double)batting.Sum(i9 => i9.H)) / ((Double)batting.Sum(i10 => i10.AB)))
                                         };
                            foreach (var s in master)
                            {
                                hofDbls.Add((double)s.Doubles);
                                hofTrips.Add((double)s.Triples);
                                hofHits.Add((double)s.Hits);
                                hofABS.Add((double)s.AB);
                                hofHRS.Add((double)s.HomeRuns);
                                hofRuns.Add((double)s.Runs);
                                hofRBIS.Add((double)s.RBI);
                                hofSBS.Add((double)s.StolenBases);
                                hofAVG.Add((double)s.Avg);
                                count++;
                            }
                        }
                    }

                    //Console.WriteLine("{0},{1},{2},{3},{4}", totalDoubles, totalTriples, totalHits, totalHomeRuns, count);
                    double hofDblsStd = newPrg.getStd(hofDbls);
                    double hofDblsMean = newPrg.getMean(hofDbls);

                    double hofTripsStd = newPrg.getStd(hofTrips);
                    double hofTripsMean = newPrg.getMean(hofTrips);

                    double hofHitsStd = newPrg.getStd(hofHits);
                    double hofHitsMean = newPrg.getMean(hofHits);

                    double hofABSStd = newPrg.getStd(hofABS);
                    double hofABSMean = newPrg.getMean(hofABS);

                    double hofHRSStd = newPrg.getStd(hofHRS);
                    double hofHRSMean = newPrg.getMean(hofHRS);

                    double hofRunsStd = newPrg.getStd(hofRuns);
                    double hofRunsMean = newPrg.getMean(hofRuns);

                    double hofRBISStd = newPrg.getStd(hofRBIS);
                    double hofRBISMean = newPrg.getMean(hofRBIS);

                    double hofSBSStd = newPrg.getStd(hofSBS);
                    double hofSBSMean = newPrg.getMean(hofSBS);

                    double hofAVGStd = newPrg.getStd(hofAVG);
                    double hofAVGMean = newPrg.getMean(hofAVG);
                    //End
                    DateTime endTime = DateTime.Now;
                    //Console.WriteLine("{0} {1}", hofDblsStd, hofDblsMean);
                    Console.WriteLine("Total records {0}", count);
                    Console.WriteLine("end printing--------");
                    //Start time
                    DateTime start = DateTime.Now;
                    var plyList = from bttr in db.Battings
                                  where (from fldgs in db.Fieldings
                                         where !fldgs.POS.Equals('P')
                                         group fldgs by fldgs.playerID into fld
                                         where fld.Count() > 10
                                         select fld.Key).Contains(bttr.playerID)
                                          &&
                                          !(from mst in db.Masters
                                            join hoff in db.HallOfFames on mst.hofID equals hoff.hofID
                                            select mst.hofID).Contains(bttr.playerID)
                                  orderby bttr.playerID
                                  group bttr by bttr.playerID into batter
                                  select new
                                  {
                                      ID = batter.Key
                                  };


                    Console.WriteLine("start for new ID");
                    double ctagain = 0;
                    foreach (var qq in plyList)
                    {
                        var mastrB = from b in db.Battings
                                     join m in db.Masters on b.playerID equals m.playerID
                                     where (qq.ID == b.playerID)
                                     group b by b.playerID into batting
                                     select new
                                     {
                                         Id = batting.Key,
                                         Doubles = batting.Average(i => i._2B),
                                         Triples = batting.Average(i2 => i2._3B),
                                         Hits = batting.Average(i3 => i3.H),
                                         AB = batting.Average(i8 => i8.AB),
                                         HomeRuns = batting.Average(i4 => i4.HR),
                                         Runs = batting.Average(i5 => i5.R),
                                         RBI = batting.Average(i6 => i6.RBI),
                                         StolenBases = batting.Average(i7 => i7.SB),
                                         Avg = (Double)(((Double)batting.Sum(i9 => i9.H)) / ((Double)batting.Sum(i10 => i10.AB)))
                                     };
                        foreach (var sq in mastrB)
                        {
                            zValueDoubles = newPrg.getZScore((Double)sq.Doubles, hofDblsMean, hofDblsStd);
                            zValueTrips = newPrg.getZScore((Double)sq.Triples, hofTripsMean, hofTripsStd);
                            zValueHits = newPrg.getZScore((Double)sq.Hits, hofHitsMean, hofHitsStd);
                            zValueABS = newPrg.getZScore((Double)sq.AB, hofABSMean, hofABSStd);
                            zValueHRS = newPrg.getZScore((Double)sq.HomeRuns, hofHRSMean, hofHRSStd);
                            zValueRuns = newPrg.getZScore((Double)sq.Runs, hofRunsMean, hofRunsStd);
                            zValueRBIS = newPrg.getZScore((Double)sq.RBI, hofRBISMean, hofRBISStd);
                            zValueSBS = newPrg.getZScore((Double)sq.StolenBases, hofSBSMean, hofSBSStd);
                            zValueAVG = newPrg.getZScore((Double)sq.Avg, hofAVGMean, hofAVGStd);
                            double totals = ((zValueDoubles + zValueTrips + zValueHits + zValueABS + zValueHRS + zValueRuns + zValueRBIS + zValueSBS + zValueAVG) / 9);
                            zscore.Add(sq.Id, totals);
                            ctagain++;

                        }
                    }
                    //endtime
                    DateTime end = DateTime.Now;
                    TimeSpan duration1 = endTime - startTime;
                    TimeSpan duration2 = end - start;
                    Console.WriteLine("Time to calculate std and mean for hall of fame players {0}, {1}", duration1.TotalMinutes, duration1.TotalSeconds);
                    Console.WriteLine("Time to calculate zscore for all batters {0}, {1}", duration2.TotalMinutes, duration2.TotalSeconds);
                    Console.WriteLine("ct for new Id {0}", ctagain);



                    Console.ReadLine();

                    //results.ToList();
                }
            }
        }
    }
}
